package cn.wu.demo.serialport.service;

import com.alibaba.fastjson.JSONObject;
import cn.wu.demo.serialport.entity.PushData;
import com.fazecast.jSerialComm.*;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ModbusService {

    public static void main(String[] args){
        while (true){
        // 配置串口参数
        String portName = "COM1"; // 修改为你的串口名称（如COM3、/dev/ttyUSB0）
        int baudRate = 9600;
        int dataBits = 8;
        int stopBits = SerialPort.ONE_STOP_BIT;
        int parity = SerialPort.NO_PARITY;

        // Modbus参数
        int slaveAddress = 10;    // 从站地址
        int startAddress = 1;     // 起始寄存器地址
        int registerCount = 50;    // 读取寄存器数量

        SerialPort serialPort = SerialPort.getCommPort(portName);
        serialPort.setComPortParameters(baudRate, dataBits, stopBits, parity);
        serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING, 1000, 0);

        if (!serialPort.openPort()) {
            System.err.println("无法打开串口！");
            return;
        }

        try {
            // 构建Modbus请求报文
            byte[] request = createReadRequest(slaveAddress, startAddress, registerCount);

            // 发送请求
            OutputStream os = serialPort.getOutputStream();
            os.write(request);
            os.flush();

            // 读取响应
            InputStream is = serialPort.getInputStream();
            byte[] response = new byte[5 + 2 * registerCount]; // 基础长度 + 数据
            int bytesRead = 0;
            long startTime = System.currentTimeMillis();
            while (bytesRead < response.length && (System.currentTimeMillis() - startTime) < 1000) {
                bytesRead += is.read(response, bytesRead, response.length - bytesRead);
            }

            // 验证CRC
            if (!checkCRC(response)) {
                System.err.println("CRC校验失败！");
                return;
            }

            // 解析数据
            int[] registers = parseResponse(response, registerCount);

            PushData pushData = new PushData();
            for (int i = 0; i < registers.length - 1; i += 2) {
                String a = Integer.toHexString(registers[i]);
                String b = Integer.toHexString(registers[i + 1]);
                float value = parseBADCToFloat(a, b);
                pushData.setReactor_num(1);
                switch(i) {
                    case 0:
                        System.out.println("SO2: " + value);
                        break;
                    case 2:
                        pushData.setSo2per(value);
                        System.out.println("SO2折算: " + value);
                        break;
                    case 4:
                        System.out.println("NOX: " + value);
                        break;
                    case 6:
                        pushData.setNoper(value);
                        System.out.println("NOX折算: " + value);
                        break;
                    case 8:
                        System.out.println("CO: " + value);
                        break;
                    case 10:
                        pushData.setCoper(value);
                        System.out.println("CO折算: " + value);
                        break;
                    case 12:
                        System.out.println("HCL: " + value);
                        break;
                    case 14:
                        pushData.setHclper(value);
                        System.out.println("HCL折算: " + value);
                        break;
                    case 16:
                        pushData.setO2per(value);
                        System.out.println("O2: " + value);
                        break;
                    case 18:
                        System.out.println("烟尘: " + value);
                        break;
                    case 20:
                        pushData.setKeliper(value);
                        System.out.println("烟尘折算: " + value);
                        break;
                    case 22:
                        pushData.setSteam_real(value);
                        System.out.println("流速（实际蒸汽流量）: " + value);
                        break;
                    case 24:
                        pushData.setTemperature_bd(value);
                        System.out.println("布袋前温度: " + value);
                        break;
                    case 26:
                        System.out.println("压力: " + value);
                        break;
                    case 28:
                        System.out.println("标准流量: " + value);
                        break;
                    case 30:
                        pushData.setH2oper(value);
                        System.out.println("湿度: " + value);
                        break;
                    case 32:
                        pushData.setTemperature_topa(value);
                        System.out.println("上部温度1: " + value);
                        break;
                    case 34:
                        pushData.setTemperature_topb(value);
                        System.out.println("上部温度2: " + value);
                        break;
                    case 36:
                        pushData.setTemperature_topm(value);
                        System.out.println("上部温度3: " + value);
                        break;
                    case 38:
                        pushData.setTemperature_mida(value);
                        pushData.setTemperature_bota(value+30);
                        System.out.println("中部温度1: " + value);
                        break;
                    case 40:
                        pushData.setTemperature_midb(value);
                        pushData.setTemperature_botb(value+30);
                        System.out.println("中部温度2: " + value);
                        break;
                    case 42:
                        pushData.setTemperature_midm(value);
                        pushData.setTemperature_botm(value+30);
                        System.out.println("中部温度3: " + value);
                        break;
                    case 44:
                        System.out.println("下部温度1: " + value);
                        break;
                    case 46:
                        System.out.println("下部温度2: " + value);
                        break;
                    case 48:
                        System.out.println("下部温度3: " + value);
                        break;
                }
            }

            JSONObject jsonObject1 = (JSONObject) JSONObject.toJSON(pushData);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH : mm : ss : SS");
            String str = sdf.format(new Date());
            System.out.println("时间："+str);
            System.out.println(jsonObject1);
            String params = jsonObject1.toString();
            push(params);
            try {
                Thread.sleep(60000);
            }catch(Exception e){
                System.out.println("线程异常："+e);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            serialPort.closePort();
        }
        }
    }
    /**
     * 将两个寄存器按照BADC格式解析为浮点数
     *
     * @param register0 寄存器0的值
     * @param register1 寄存器1的值
     * @return 解析后的浮点数
     */
    private static float parseBADCToFloat(String register0, String register1) {
        // 将16进制字符串转换为整数
        int reg0 = Integer.parseInt(register0, 16);
        int reg1 = Integer.parseInt(register1, 16);

        // 将寄存器值拆分为字节
        byte[] bytes = new byte[4];
        bytes[0] = (byte) ((reg1 >> 8) & 0xFF); // 寄存器1的高字节
        bytes[1] = (byte) (reg1 & 0xFF);       // 寄存器1的低字节
        bytes[2] = (byte) ((reg0 >> 8) & 0xFF); // 寄存器0的高字节
        bytes[3] = (byte) (reg0 & 0xFF);       // 寄存器0的低字节

        // 将字节数组转换为32位整数
        int intBits = ((bytes[0] & 0xFF) << 24) |
                ((bytes[1] & 0xFF) << 16) |
                ((bytes[2] & 0xFF) << 8) |
                (bytes[3] & 0xFF);

        // 将32位整数转换为浮点数
        return Float.intBitsToFloat(intBits);
    }
    private static byte[] createReadRequest(int slaveAddress, int startAddress, int registerCount) {
        byte[] request = new byte[8];
        request[0] = (byte) slaveAddress;          // 从站地址
        request[1] = 0x03;                       // 功能码：读保持寄存器
        request[2] = (byte) (startAddress >> 8);  // 起始地址高字节
        request[3] = (byte) (startAddress & 0xFF); // 起始地址低字节
        request[4] = (byte) (registerCount >> 8);  // 寄存器数量高字节
        request[5] = (byte) (registerCount & 0xFF);// 寄存器数量低字节

        // 计算CRC
        int crc = calculateCRC(request, 0, 6);
        request[6] = (byte) (crc & 0xFF);
        request[7] = (byte) ((crc >> 8) & 0xFF);

        return request;
    }

    private static int[] parseResponse(byte[] response, int registerCount) {
        int[] registers = new int[registerCount];
        for (int i = 0; i < registerCount; i++) {
            int pos = 3 + 2 * i;
            registers[i] = ((response[pos] & 0xFF) << 8) | (response[pos + 1] & 0xFF);
        }
        return registers;
    }

    private static boolean checkCRC(byte[] data) {
        int length = data.length - 2;
        int crc = calculateCRC(data, 0, length);
        return (data[length] == (byte) (crc & 0xFF))
                && (data[length + 1] == (byte) ((crc >> 8) & 0xFF));
    }

    private static int calculateCRC(byte[] data, int offset, int length) {
        int crc = 0xFFFF;
        for (int i = offset; i < offset + length; i++) {
            crc ^= (data[i] & 0xFF);
            for (int j = 0; j < 8; j++) {
                if ((crc & 0x0001) != 0) {
                    crc = (crc >> 1) ^ 0xA001;
                } else {
                    crc >>= 1;
                }
            }
        }
        return crc;
    }

    public static void push(String params){

        BufferedReader reader = null;
        try {
            URL url = new URL("http://www.czzhcs001.com/api.php/online/compute/index");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setInstanceFollowRedirects(true);
            connection.setRequestMethod("POST"); //
            connection.setRequestProperty("Content-Type", "application/json");
            connection.connect();
            OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
            out.append(params);
            out.flush();
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            System.out.println(connection.getResponseCode());
            String line;
            String res = "";
            while ((line = reader.readLine()) != null) {
                res += line;
            }
            reader.close();
            System.out.println(res);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}